package com.huawei.cloud.phone.management.common.security;

import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.NonNull;

import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;

@NoArgsConstructor
@Slf4j
public class AesEncryptionServiceImpl implements EncryptionService {
    private static final int TAG_LENGTH = 128;

    private String hexAesKey = "1a2b3c4d5e6f70819203a4b5c6d7e8f9";

    private String hexIv = "f0e1d2c3b4a5968778695a4b3c2d1e0f";

    public AesEncryptionServiceImpl(@NonNull String key, @NonNull String iv) {
        this.hexAesKey = key;
        this.hexIv = iv;
    }

    @Override
    public String encrypt(@NonNull String plainText) {
        byte[] sKey = hexToByteArray(hexAesKey);

        // 还原盐值的byte
        byte[] iv = hexToByteArray(hexIv);

        try {
            SecretKeySpec secretKeySpec = new SecretKeySpec(sKey, "AES");
            Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");

            GCMParameterSpec ivParameterSpec = new GCMParameterSpec(TAG_LENGTH, iv);
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);

            byte[] encrypted = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
            return bytesToHex(encrypted);
        } catch (Exception e) {
            log.error("AESBaseEncrypt Exception", e);
        }
        return "";
    }

    @Override
    public String decrypt(@NonNull String cipherText) {
        byte[] sKey = hexToByteArray(hexAesKey);

        byte[] iv = hexToByteArray(hexIv);

        try {
            SecretKeySpec sKeySpec = new SecretKeySpec(sKey, "AES");
            Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
            GCMParameterSpec ivParameterSpec = new GCMParameterSpec(TAG_LENGTH, iv);

            cipher.init(Cipher.DECRYPT_MODE, sKeySpec, ivParameterSpec);
            byte[] srcByte = hexToByteArray(cipherText);
            byte[] original = cipher.doFinal(srcByte);
            return new String(original, StandardCharsets.UTF_8);
        } catch (Exception e) {
            log.error("AESBaseDecrypt error", e);
        }
        return "";
    }


    public byte[] hexToByteArray(String inHex) {
        int hexLen = inHex.length();
        byte[] result;
        if ((hexLen & 1) == 1) {
            // 奇数
            hexLen++;
            result = new byte[(hexLen / 2)];
            inHex = "0" + inHex;
        } else {
            // 偶数
            result = new byte[(hexLen / 2)];
        }
        int index = 0;
        for (int position = 0; position < hexLen; position += 2) {
            result[index++] = hexToByte(inHex.substring(position, position + 2));
        }
        return result;
    }

    private byte hexToByte(String inHex) {
        return (byte) Integer.parseInt(inHex, 16);
    }

    private String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte aByte : bytes) {
            String hex = Integer.toHexString(aByte & 0xFF);
            if (hex.length() < 2) {
                sb.append(0);
            }
            sb.append(hex);
        }
        return sb.toString();
    }
}
